1 /*
2 * Angkor Web Framework
3 *
4 * Distributable under LGPL license.
5 * See terms of license at gnu.org.
6 */
7 package com.tirsen.angkor.event;
8
9 import com.tirsen.angkor.Application;
10 import com.tirsen.angkor.Debug;
11 import com.tirsen.angkor.Multicaster;
12 import org.apache.log4j.Category;
13
14 import java.lang.reflect.InvocationTargetException;
15 import java.lang.reflect.Method;
16 import java.util.ArrayList;
17 import java.util.EventListener;
18 import java.util.EventObject;
19 import java.util.Iterator;
20 import java.util.LinkedList;
21 import java.util.List;
22
23 /***
24 * The EventQueue is used to schedule the sending of events until just before the render-phase.
25 * This is to ensure that all models have been updated before event-processing.
26 * Q: with the new model with separated smaller components there are several parse and render-phases
27 * this means that the events will only be queued up for each component. This might prove to be acceptable
28 * though.
29 * A: This is resolved for the following reason, during the render phase components are registered for parsing
30 * when the request returns the ApplicationFilter starts the parse phase which ends with the RenderContext resetting
31 * the list of registered parsing components, when the RenderContext is ready with this the ApplicationFilter
32 * passes the request to the FilterChain. This means that all components from the previous request are parsed before
33 * the jsps or components are rendered.
34 * Q: In what order are events sent?
35 * A: Events can not be ordered in the same sense as in a Swing application when it comes to a web application.
36 * Therefor some kind of guessing needs to be applied to in what order events are to be processed. A pre-defined
37 * ordering of events are applied. This could be: ViewLinkEvent, <all other event types>, ActionEvent.
38 * @author $Author: tirsen $
39 * @version $Revision: 1.4 $
40 * <BR>
41 * $Id: EventQueue.java,v 1.4 2002/10/13 13:37:26 tirsen Exp $
42 */
43 public class EventQueue
44 {
45 private static final Category logger = Debug.getCategory();
46
47 private List queue = new LinkedList();
48 private boolean postponeEvents = true;
49
50 public static class QueuedEvent
51 {
52 private Class listenerInterface;
53 private EventListener target;
54 private EventObject event;
55 private String method;
56
57 public QueuedEvent(Class listenerInterface, EventListener target, EventObject event, String method)
58 {
59 this.listenerInterface = listenerInterface;
60 this.target = target;
61 this.event = event;
62 this.method = method;
63 }
64
65 public void send(Application application) throws Exception
66 {
67 logger.debug("sending event " + event + " to " + target);
68 logger.debug("calling method " + method);
69 Method m = listenerInterface.getMethod(method, new Class[]{event.getClass()});
70 try
71 {
72 m.invoke(target, new Object[]{event});
73 }
74 catch (InvocationTargetException e)
75 {
76 Multicaster.throwRealException(e);
77 }
78 }
79
80 public EventObject getEvent()
81 {
82 return event;
83 }
84 }
85
86 /***
87 * Currently does not queue up events to be sent later on. Rather they are sent immediately.
88 * TODO: queue up events.
89 * Note that further events can of course be sent while sending events.
90 */
91 public void postEvent(Class listenerInterface, EventListener target, EventObject event, String method)
92 {
93 QueuedEvent queuedEvent = new QueuedEvent(listenerInterface, target, event, method);
94 if (postponeEvents)
95 {
96 queue.add(queuedEvent);
97 }
98 else
99 {
100 try
101 {
102 queuedEvent.send(Application.getApplication());
103 }
104 catch (Exception e)
105 {
106 Application.getApplication().handleError(e);
107 }
108 }
109 }
110
111 public void setPostponeEvents(boolean postponeEvents)
112 {
113 this.postponeEvents = postponeEvents;
114 }
115
116 /***
117 * Sends the events and clears the event queue.
118 */
119 public void processEvents(Application application) throws Exception
120 {
121 for (Iterator iterator = iterateEvents(); iterator.hasNext();)
122 {
123 QueuedEvent event = (QueuedEvent) iterator.next();
124 event.send(application);
125 if (application != null && application.getError() != null) break;
126 }
127 reset();
128 }
129
130 /***
131 * Returns a thread safe iterator over the current events. Events can be added while
132 * using this iterator but they will not be added to this iterator. To process the events
133 * posted while processing these events another iterator must be added.
134 */
135 public Iterator iterateEvents()
136 {
137 return new ArrayList(queue).iterator();
138 }
139
140 public void reset()
141 {
142 queue.clear();
143 }
144 }
This page was automatically generated by Maven